﻿namespace Microsoft.VisualStudio.TestTools.UnitTesting
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Diagnostics.Contracts;

    /// <summary>
    /// Holds test information.
    /// </summary>
    /// <typeparam name="TTuple">The type of the tuple.</typeparam>
    [DebuggerStepThrough]
    public class ListItemCollection<TTuple> : IEnumerable<TTuple>
    {
        private List<TTuple> items = new List<TTuple>();

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="ListItemCollection&lt;TTuple&gt;"/> class.
        /// </summary>
        internal ListItemCollection()
        {
        }
        #endregion Constructors

        #region Public Methods
        /// <summary>
        /// Adds the item.
        /// </summary>
        /// <param name="item">The item to add.</param>
        /// <returns>The collection of items.</returns>
        public ListItemCollection<TTuple> AddItem(TTuple item)
        {
            Contract.Requires(item != null);
            Contract.Ensures(Contract.Result<ListItemCollection<TTuple>>() != null);

            this.items.Add(item);

            return this;
        }

        /// <summary>
        /// Removes all the items from the collection.
        /// </summary>
        /// <returns>The collection of items.</returns>
        public ListItemCollection<TTuple> Clear()
        {
            Contract.Ensures(this.items.Count == 0);

            this.items.Clear();

            return this;
        }

        /// <summary>
        /// Returns an enumerator that iterates through the collection.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
        /// </returns>
        public IEnumerator<TTuple> GetEnumerator()
        {
            Contract.Ensures(Contract.Result<IEnumerator<TTuple>>() != null);

            return this.items.GetEnumerator();
        }

        /// <summary>
        /// Removes the items.
        /// </summary>
        /// <param name="predicate">The predicate that determines which items to remove.</param>
        /// <returns>The collection of items.</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Contracts", "Requires", Justification = "The i index is always valid.")]
        public ListItemCollection<TTuple> RemoveItems(Func<TTuple, bool> predicate)
        {
            if (predicate == null)
            {
                throw new ArgumentNullException("predicate");
            }

            Contract.EndContractBlock();

            for (int i = this.items.Count - 1; i >= 0; i--)
            {
                if (predicate(this.items[i]))
                {
                    this.items.RemoveAt(i);
                }
            }

            return this;
        }
        #endregion Public Methods

        #region IEnumerable Members
        /// <summary>
        /// Returns an enumerator that iterates through a collection.
        /// </summary>
        /// <returns>An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.</returns>
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.items.GetEnumerator();
        }
        #endregion
    }
}